home *** CD-ROM | disk | FTP | other *** search
/ Programmer Power Tools / Programmer Power Tools.iso / editor / j414src.arc / BUF.C < prev    next >
C/C++ Source or Header  |  1989-10-10  |  14KB  |  696 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. /* Contains commands that deal with creating, selecting, killing and
  9.    listing buffers, and buffer modes, and find-file, etc. */
  10.  
  11. #include "jove.h"
  12. #include "ctype.h"
  13. #include "disp.h"
  14. #if defined(IPROCS)
  15. # include "fp.h"
  16. # include "iproc.h"
  17. #endif
  18.  
  19. #ifdef MAC
  20. # include "mac.h"
  21. #else
  22. # include <sys/stat.h>
  23. #endif
  24.  
  25. private Buffer
  26.     *buf_alloc proto((void)),
  27.     *mak_buf proto((void));
  28.  
  29. private char *line_cnt proto((Buffer *, char *));
  30.  
  31. private void
  32.     defb_wind proto((Buffer *)),
  33.     kill_buf proto((Buffer *)),
  34.     mkbuflist proto((char **));
  35.  
  36. private char    *Mainbuf = "Main",
  37.     *NoName = "Sans un nom!";
  38.  
  39. Buffer    *world = 0,        /* First in the list */
  40.     *curbuf = 0,    /* pointer into world for current buffer */
  41.     *lastbuf = 0;    /* Last buffer we were in so we have a default
  42.                buffer during a select buffer. */
  43.  
  44. /* Toggle BIT in the current buffer's minor mode flags.  If argument is
  45.    supplied, a positive one always turns on the mode and zero argument
  46.    always turns it off. */
  47.  
  48. void
  49. TogMinor(bit)
  50. int    bit;
  51. {
  52.     if (is_an_arg()) {
  53.         if (arg_value() == 0)
  54.             curbuf->b_minor &= ~bit;
  55.         else
  56.             curbuf->b_minor |= bit;
  57.     } else
  58.         curbuf->b_minor ^= bit;
  59.     UpdModLine = YES;
  60. }
  61.  
  62. /* Creates a new buffer, links it at the end of the buffer chain, and
  63.    returns it. */
  64.  
  65. private Buffer *
  66. buf_alloc()
  67. {
  68.     register Buffer    *b,
  69.             *lastbp;
  70.  
  71.     lastbp = 0;
  72.     for (b = world; b != 0; lastbp = b, b = b->b_next)
  73.         ;
  74.  
  75.     b = (Buffer *) emalloc(sizeof (Buffer));
  76.     if (lastbp)
  77.         lastbp->b_next = b;
  78.     else
  79.         world = b;
  80.     b->b_first = 0;
  81.     b->b_next = 0;
  82. #if defined(MAC)
  83.     b->Type = BUFFER;    /* kludge, but simplifies menu handlers */
  84.     b->Name = 0;
  85. #endif
  86.     return b;
  87. }
  88.  
  89. /* Makes a buffer and initializes it.  Obsolete.  Used to take two
  90.    arguments, a buffer name and a file name. */
  91.  
  92. private Buffer *
  93. mak_buf()
  94. {
  95.     register Buffer    *newb;
  96.     register int    i;
  97.  
  98.     newb = buf_alloc();
  99.     newb->b_fname = 0;
  100.     newb->b_name = NoName;
  101.     set_ino(newb);
  102.     newb->b_marks = 0;
  103.     newb->b_themark = 0;        /* Index into markring */
  104.     /* No marks yet */
  105.     for (i = 0; i < NMARKS; i++)
  106.         newb->b_markring[i] = 0;
  107.     newb->b_modified = 0;
  108.     newb->b_type = B_FILE;  /* File until proven SCRATCH */
  109.     newb->b_ntbf = 0;
  110.     newb->b_minor = 0;
  111.     newb->b_major = TEXT;
  112.     newb->b_first = 0;
  113.     newb->b_map = 0;
  114. #if defined(IPROCS)
  115.     newb->b_process = 0;
  116. #endif
  117.     initlist(newb);
  118. #if defined(MAC)
  119.     Bufchange = 1;
  120. #endif
  121.     return newb;
  122. }
  123.  
  124. void
  125. ReNamBuf()
  126. {
  127.     register char    *new = 0,
  128.             *prompt = ProcFmt,
  129.             *second = "%s already exists; new name? ";
  130.  
  131.     for (;;) {
  132.         new = ask((char *) 0, prompt, new);
  133.         if (!buf_exists(new))
  134.             break;
  135.         prompt = second;
  136.     }
  137.     setbname(curbuf, new);
  138. }
  139.  
  140. void
  141. FindFile()
  142. {
  143.     register char    *name;
  144.     char    fnamebuf[FILESIZE];
  145.  
  146.     name = ask_file((char *) 0, curbuf->b_fname, fnamebuf);
  147.     SetABuf(curbuf);
  148.     SetBuf(do_find(curwind, name, 0));
  149. }
  150.  
  151. private void
  152. mkbuflist(bnamp)
  153. register char    **bnamp;
  154. {
  155.     register Buffer    *b;
  156.  
  157.     for (b = world; b != 0; b = b->b_next)
  158.         if (b->b_name != 0)
  159.             *bnamp++ = b->b_name;
  160.     *bnamp = 0;
  161. }
  162.  
  163. char *
  164. ask_buf(def)
  165. Buffer    *def;
  166. {
  167.     char    *bnames[100];
  168.     register char    *bname;
  169.     register int    offset;
  170.     char    prompt[100];
  171.  
  172.     if (def != 0 && def->b_name != 0)
  173.         swritef(prompt, ": %f (default %s) ", def->b_name);
  174.     else
  175.         swritef(prompt, ProcFmt);
  176.     mkbuflist(bnames);
  177.     offset = complete(bnames, prompt, RET_STATE);
  178.     if (offset == EOF)
  179.         complain((char *) 0);
  180.     if (offset == ORIGINAL || offset == AMBIGUOUS)
  181.         bname = Minibuf;
  182.     else if (offset == NULLSTRING) {
  183.         if (def)
  184.             bname = def->b_name;
  185.         else
  186.             complain((char *) 0);
  187.     } else if (offset < 0)
  188.         complain((char *) 0);
  189.     else
  190.         bname = bnames[offset];
  191.  
  192.     return bname;
  193. }
  194.  
  195. void
  196. BufSelect()
  197. {
  198.     register char    *bname;
  199.  
  200.     bname = ask_buf(lastbuf);
  201.     SetABuf(curbuf);
  202.     SetBuf(do_select(curwind, bname));
  203. }
  204.  
  205. #if defined(MSDOS)
  206.  
  207. private void
  208. BufNSelect(n)
  209. {
  210.     char *bnames[100];
  211.     char *bname;
  212.     int i;
  213.  
  214.     mkbuflist(bnames);
  215.     for (i=0; i<n; i++)
  216.         if (bnames[i] == 0)
  217.            complain("[No such buffer]");
  218.     bname = bnames[n-1];
  219.     SetABuf(curbuf);
  220.     SetBuf(do_select(curwind, bname));
  221. }
  222.  
  223. void Buf1Select() { BufNSelect(1); }
  224. void Buf2Select() { BufNSelect(2); }
  225. void Buf3Select() { BufNSelect(3); }
  226. void Buf4Select() { BufNSelect(4); }
  227. void Buf5Select() { BufNSelect(5); }
  228. void Buf6Select() { BufNSelect(6); }
  229. void Buf7Select() { BufNSelect(7); }
  230. void Buf8Select() { BufNSelect(8); }
  231. void Buf9Select() { BufNSelect(9); }
  232. void Buf10Select() { BufNSelect(10); }
  233.  
  234. #endif /* MSDOS */
  235.  
  236. private void
  237. defb_wind(b)
  238. register Buffer *b;
  239. {
  240.     register Window    *w = fwind;
  241.     char    *alt;
  242.  
  243.     if (lastbuf == b || lastbuf == 0) {
  244.         lastbuf = 0;
  245.         alt = (b->b_next != 0) ? b->b_next->b_name : Mainbuf;
  246.     } else
  247.         alt = lastbuf->b_name;
  248.  
  249.     do {
  250.         if (w->w_bufp == b) {
  251.             if (one_windp() || alt != Mainbuf)
  252.                 (void) do_select(w, alt);
  253.             else {
  254.                 Window    *save = w->w_next;
  255.  
  256.                 del_wind(w);
  257.                 w = save->w_prev;
  258.             }
  259.         }
  260.         w = w->w_next;
  261.     } while (w != fwind || w->w_bufp == b);
  262. }
  263.  
  264. private Buffer *
  265. getNMbuf()
  266. {
  267.     register Buffer    *delbuf;
  268.     register char    *bname;
  269.  
  270.     bname = ask_buf(curbuf);
  271.     if ((delbuf = buf_exists(bname)) == 0)
  272.         complain("[No such buffer]");
  273.     if (delbuf->b_modified)
  274.         confirm("%s modified, are you sure? ", bname);
  275.     return delbuf;
  276. }
  277.  
  278. void
  279. BufErase()
  280. {
  281.     register Buffer    *delbuf;
  282.  
  283.     if ((delbuf = getNMbuf()) != NIL) {
  284.         initlist(delbuf);
  285.         delbuf->b_modified = 0;
  286.     }
  287. }
  288.  
  289. private void
  290. kill_buf(delbuf)
  291. register Buffer    *delbuf;
  292. {
  293.     register Buffer    *b,
  294.             *lastb = 0;
  295.  
  296. #if defined(IPROCS)
  297.     pbuftiedp(delbuf);    /* check for lingering processes */
  298. #endif
  299.     /* clean up windows associated with this buffer */
  300.     if (delbuf == curbuf)
  301.         curbuf = NULL;
  302.     if (delbuf == lastbuf)
  303.         lastbuf = curbuf;    /* even if NULL */
  304.     defb_wind(delbuf);
  305.     if (curbuf == NULL)
  306.         SetBuf(curwind->w_bufp);
  307.  
  308.     /* unlink the buffer */
  309.     for (b = world; b != 0; lastb = b, b = b->b_next)
  310.         if (b == delbuf)
  311.             break;
  312.     if (lastb)
  313.         lastb->b_next = delbuf->b_next;
  314.     else
  315.         world = delbuf->b_next;
  316.  
  317. #if !defined(MAC)
  318.     if (perr_buf == delbuf) {
  319.         ErrFree();
  320.         perr_buf = 0;
  321.     }
  322. #endif
  323.  
  324.     lfreelist(delbuf->b_first);
  325.     if (delbuf->b_name)
  326.         free(delbuf->b_name);
  327.     if (delbuf->b_fname)
  328.         free(delbuf->b_fname);
  329.     flush_marks(delbuf);
  330.     free((char *) delbuf);
  331.  
  332. #if defined(MAC)
  333.     Bufchange = 1;
  334. #endif
  335. }
  336.  
  337. /* offer to kill some buffers */
  338.  
  339. void
  340. KillSome()
  341. {
  342.     register Buffer    *b,
  343.             *next;
  344.     Buffer    *oldb;
  345.     register char    *y_or_n;
  346.  
  347.     for (b = world; b != 0; b = next) {
  348.         next = b->b_next;
  349.         if (yes_or_no_p("Kill %s? ", b->b_name) == NO)
  350.             continue;
  351.         if (IsModified(b)) {
  352.             y_or_n = ask("No", "%s modified; should I save it? ", b->b_name);
  353.             if (CharUpcase(*y_or_n) == 'Y') {
  354.                 oldb = curbuf;
  355.                 SetBuf(b);
  356.                 SaveFile();
  357.                 SetBuf(oldb);
  358.             }
  359.         }
  360.         kill_buf(b);
  361.     }
  362. }
  363.  
  364. void
  365. BufKill()
  366. {
  367.     Buffer    *b;
  368.  
  369.     if ((b = getNMbuf()) == 0)
  370.         return;
  371.     kill_buf(b);
  372. }
  373.  
  374. private char *
  375. line_cnt(b, buf)
  376. register Buffer    *b;
  377. char    *buf;
  378. {
  379.     register int    nlines = 0;
  380.     register Line    *lp;
  381.  
  382.     for (lp = b->b_first; lp != 0; lp = lp->l_next, nlines++)
  383.         ;
  384.     swritef(buf, "%d", nlines);
  385.     return buf;
  386. }
  387.  
  388. private const char    *const TypeNames[] = {
  389.     0,
  390.     "Scratch",
  391.     "File",
  392.     "Process",
  393. };
  394.  
  395. void
  396. BufList()
  397. {
  398.     register char    *fmt = "%-2s %-5s %-11s %-1s %-*s  %-s";
  399.     register Buffer    *b;
  400.     int    bcount = 1,        /* To give each buffer a number */
  401.         buf_width = 11;
  402.     char    nbuf[10];
  403.  
  404.     for (b = world; b != 0; b = b->b_next)
  405.         buf_width = max(buf_width, (int)strlen(b->b_name));
  406.  
  407.     TOstart("Buffer list", TRUE);    /* true means auto-newline */
  408.  
  409.     Typeout("(* means buffer needs saving)");
  410.     Typeout("(+ means file hasn't been read yet)");
  411.     Typeout(NullStr);
  412.     Typeout(fmt, "NO", "Lines", "Type", NullStr, buf_width, "Name", "File");
  413.     Typeout(fmt, "--", "-----", "----", NullStr, buf_width, "----", "----");
  414.     for (b = world; b != 0; b = b->b_next) {
  415.         Typeout(fmt, itoa(bcount++),
  416.                 line_cnt(b, nbuf),
  417.                 TypeNames[b->b_type],
  418.                 IsModified(b) ? "*" :
  419.                      b->b_ntbf ? "+" : NullStr,
  420.                 buf_width,
  421.                 /* For the * (variable length field) */
  422.                 b->b_name,
  423.                 filename(b));
  424.  
  425.         if (TOabort)
  426.             break;
  427.     }
  428.     TOstop();
  429. }
  430.  
  431. void
  432. bufname(b)
  433. register Buffer    *b;
  434. {
  435.     char    tmp[100],
  436.         *cp;
  437.     int    try = 1;
  438.  
  439.     if (b->b_fname == 0)
  440.         complain("[No file name]");
  441.     cp = basename(b->b_fname);
  442.     strcpy(tmp, cp);
  443.     while (buf_exists(tmp)) {
  444.         swritef(tmp, "%s.%d", cp, try);
  445.         try += 1;
  446.     }
  447.     setbname(b, tmp);
  448. }
  449.  
  450. void
  451. initlist(b)
  452. register Buffer    *b;
  453. {
  454.     lfreelist(b->b_first);
  455.     b->b_first = b->b_dot = b->b_last = 0;
  456.     (void) listput(b, b->b_first);
  457.  
  458.     SavLine(b->b_dot, NullStr);
  459.     b->b_char = 0;
  460.     AllMarkSet(b, b->b_dot, 0);
  461.     if (b == curbuf)
  462.         getDOT();
  463. }
  464.  
  465. /* Returns pointer to buffer with name NAME, or if NAME is a string of digits
  466.    returns the buffer whose number equals those digits.  Otherwise, returns
  467.    0. */
  468.  
  469. Buffer *
  470. buf_exists(name)
  471. register char    *name;
  472. {
  473.     register Buffer    *bp;
  474.     int    n;
  475.  
  476.     if (name == 0)
  477.         return 0;
  478.  
  479.     for (bp = world; bp != 0; bp = bp->b_next)
  480.         if (strcmp(bp->b_name, name) == 0)
  481.             return bp;
  482.  
  483.     /* Doesn't match any names.  Try for a buffer number... */
  484.  
  485.     if (chr_to_int(name, 10, YES, &n) != INT_BAD) {
  486.         for (bp = world; n > 1; bp = bp->b_next) {
  487.             if (bp == 0)
  488.                 break;
  489.             n -= 1;
  490.         }
  491.         return bp;
  492.     }
  493.  
  494.     return 0;
  495. }
  496.  
  497. /* Returns buffer pointer with a file name NAME, if one exists.  Stat's the
  498.    file and compares inodes, in case NAME is a link, as well as the actual
  499.    characters that make up the file name. */
  500.  
  501. Buffer *
  502. file_exists(name)
  503. register char    *name;
  504. {
  505.     struct stat    stbuf;
  506.     register struct stat    *s = &stbuf;
  507.     register Buffer    *b = 0;
  508.     char    fnamebuf[FILESIZE];
  509.  
  510. #if defined(MSDOS)
  511.     strlwr(name);
  512. #endif /* MSDOS */
  513.     if (name) {
  514.         PathParse(name, fnamebuf);
  515.         if (stat(fnamebuf, s) == -1)
  516.             s->st_ino = 0;
  517.         for (b = world; b != 0; b = b->b_next) {
  518.             if (
  519. #if !defined(MSDOS)
  520.                 (b->b_ino != 0 && b->b_ino == s->st_ino &&
  521.                  b->b_dev != 0 && b->b_dev == s->st_dev) ||
  522. #endif /* MSDOS */
  523.                 (b->b_fname != 0 &&
  524.                  strcmp(b->b_fname, fnamebuf) == 0))
  525.                 break;
  526.         }
  527.     }
  528.     return b;
  529. }
  530.  
  531. void
  532. setbname(b, name)
  533. register Buffer    *b;
  534. register char    *name;
  535. {
  536.     UpdModLine = YES;    /* Kludge ... but speeds things up considerably */
  537.     if (name) {
  538.         if (b->b_name == NoName)
  539.             b->b_name = 0;
  540.         b->b_name = ralloc(b->b_name, strlen(name) + 1);
  541.         strcpy(b->b_name, name);
  542.     } else
  543.         b->b_name = 0;
  544. #if defined(MAC)
  545.     Bufchange = 1;
  546. #endif
  547. }
  548.  
  549. void
  550. setfname(b, name)
  551. register Buffer    *b;
  552. register char    *name;
  553. {
  554.     char    wholename[FILESIZE],
  555.         oldname[FILESIZE],
  556.         *oldptr = oldname;
  557.     Buffer    *save = curbuf;
  558.  
  559.     SetBuf(b);
  560.     UpdModLine = YES;    /* Kludge ... but speeds things up considerably */
  561.     if (b->b_fname == 0)
  562.         oldptr = 0;
  563.     else
  564.         strcpy(oldname, b->b_fname);
  565.     if (name) {
  566. #if defined(MSDOS)
  567.         strlwr(name);
  568. #endif /* MSDOS */
  569.         PathParse(name, wholename);
  570.         curbuf->b_fname = ralloc(curbuf->b_fname, strlen(wholename) + 1);
  571.         strcpy(curbuf->b_fname, wholename);
  572.     } else
  573.         b->b_fname = 0;
  574.     DoAutoExec(curbuf->b_fname, oldptr);
  575.     curbuf->b_mtime = curbuf->b_dev = curbuf->b_ino = 0;    /* until they're known. */
  576.     SetBuf(save);
  577. #if defined(MAC)
  578.     Bufchange = 1;
  579. #endif
  580. }
  581.  
  582. void
  583. set_ino(b)
  584. register Buffer    *b;
  585. {
  586.     struct stat    stbuf;
  587.  
  588.     if (b->b_fname == 0 || stat(pr_name(b->b_fname, NO), &stbuf) == -1) {
  589.         b->b_dev = 0;
  590.         b->b_ino = 0;
  591.         b->b_mtime = 0;
  592.     } else {
  593.         b->b_dev = stbuf.st_dev;
  594.         b->b_ino = stbuf.st_ino;
  595.         b->b_mtime = stbuf.st_mtime;
  596.     }
  597. }
  598.  
  599. /* Find the file `fname' into buf and put in in window `w' */
  600.  
  601. Buffer *
  602. do_find(w, fname, force)
  603. register Window    *w;
  604. register char    *fname;
  605. int    force;
  606. {
  607.     register Buffer    *b;
  608.  
  609.     b = file_exists(fname);
  610.     if (b == 0) {
  611.         b = mak_buf();
  612.         setfname(b, fname);
  613.         bufname(b);
  614.         set_ino(b);
  615.         b->b_ntbf = 1;
  616.     }
  617.     if (force) {
  618.         Buffer    *oldb = curbuf;
  619.  
  620.         SetBuf(b);    /* this'll read the file */
  621.         SetBuf(oldb);
  622.     }
  623.     if (w)
  624.         tiewind(w, b);
  625.     return b;
  626. }
  627.  
  628. /* set alternate buffer */
  629.  
  630. void
  631. SetABuf(b)
  632. Buffer    *b;
  633. {
  634.     if (b != 0)
  635.         lastbuf = b;
  636. }
  637.  
  638.  
  639. /* check to see if BP is a valid buffer pointer */
  640. private int
  641. valid_bp(bp)
  642. register Buffer    *bp;
  643. {
  644.     register Buffer    *b;
  645.  
  646.     for (b = world; b != 0; b = b->b_next)
  647.         if (b == bp)
  648.             break;
  649.     return b != 0;
  650. }
  651.  
  652. void
  653. SetBuf(newbuf)
  654. register Buffer    *newbuf;
  655. {
  656.     if (newbuf == curbuf || newbuf == 0)
  657.         return;
  658.  
  659.     if (!valid_bp(newbuf))
  660.         complain("Internal error: (0x%x) is not a valid buffer pointer!", newbuf);
  661.     lsave();
  662.     curbuf = newbuf;
  663.     curline = newbuf->b_dot;
  664.     curchar = newbuf->b_char;
  665.     getDOT();
  666.     /* do the read now ... */
  667.     if (curbuf->b_ntbf)
  668.         read_file(curbuf->b_fname, 0);
  669. #if defined(MAC)
  670.     Modechange = 1;
  671. #endif
  672. }
  673.  
  674. Buffer *
  675. do_select(w, name)
  676. register Window    *w;
  677. register char    *name;
  678. {
  679.     register Buffer    *new;
  680.  
  681.     if ((new = buf_exists(name)) == 0) {
  682.         new = mak_buf();
  683.         setfname(new, (char *) 0);
  684.         setbname(new, name);
  685.     }
  686.     if (w)
  687.         tiewind(w, new);
  688.     return new;
  689. }
  690.  
  691. void
  692. buf_init()
  693. {
  694.     SetBuf(do_select(curwind, Mainbuf));
  695. }
  696.